using UnityEngine;
using UnityEditor;
using System.Collections;

public class CreateCharacterWizard : ScriptableObject
{
	static Transform FindParentTransformWithComponent<T>(Transform from) where T : Component
	{
		for(Transform transform = from; transform != null; transform = transform.parent)
		{
			if(transform.GetComponent<T>() != null)
			{
				return transform;
			}
		}
		
		return null;
	}
	
	static void ClearLocalTransform(Transform transform)
	{
		transform.localPosition = Vector3.zero;
		transform.localRotation = Quaternion.identity;
		transform.localScale = Vector3.one;
	}
	
	[MenuItem ("Character/Set Selection To Character")]  
	static void SetSelectionToCharacter()  
	{  
		Transform[] transforms = Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.OnlyUserModifiable);  
		
		foreach(Transform transform in transforms)  
		{  
			GameObject character = new GameObject("Character");  
			transform.parent = character.transform;
			Character characterScipt = character.AddComponent<Character>();
			characterScipt.animationRef = transform.GetComponent<Animation>();
			
			
			GameObject states = new GameObject("States");
			states.transform.parent = character.transform;
			ClearLocalTransform(states.transform);
			states.layer = character.layer;
		}  
	}  
	
	[MenuItem ("Character/Add New State")]  
	static void AddState()  
	{  
		Transform[] transforms = Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.OnlyUserModifiable);
		
		Transform parent = null;
		if(transforms != null && transforms.Length > 0)
		{
			Transform character = FindParentTransformWithComponent<Character>(transforms[0]);
			if(character != null)
				parent = character.FindChild("States");
		}
		
		GameObject state = new GameObject("State");
		state.AddComponent<CharacterAnimatedState>();
		state.transform.parent = parent;
		ClearLocalTransform(state.transform);
		state.layer = parent.gameObject.layer;
		
		GameObject alwaysFrame = new GameObject("Always");
		alwaysFrame.AddComponent<CharacterKeyFrame>().always = true;
		alwaysFrame.transform.parent = state.transform;
		ClearLocalTransform(alwaysFrame.transform);
		alwaysFrame.layer = state.layer;
	}  
	
	[MenuItem ("Character/Add New Key Frame")]  
	public static void AddKeyFrame()
	{
		Transform[] transforms = Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.OnlyUserModifiable);
		
		Transform parent = null;
		if(transforms != null && transforms.Length > 0)
		{
			parent = FindParentTransformWithComponent<CharacterAnimatedState>(transforms[0]);
		}
		
		GameObject keyFrame = new GameObject("Frame0");
		keyFrame.AddComponent<CharacterKeyFrame>();
		keyFrame.transform.parent = parent;
		ClearLocalTransform(keyFrame.transform);
		keyFrame.layer = parent.gameObject.layer;
	}
	
	#region create action
	static Transform FindParentForFrameAction()
	{
		Transform[] transforms = Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.OnlyUserModifiable);
		Transform parent = null;
		if(transforms != null && transforms.Length > 0)
		{
			Transform state = FindParentTransformWithComponent<CharacterKeyFrame>(transforms[0]);
			if(state != null)
				parent = state;
			else
				parent = transforms[0];
		}
		
		return parent;
	}
	
	static T CreateNewFrameAction<T>()  where T : Component
	{
		Transform transform = FindParentForFrameAction();
		
		if(transform != null)
		{
			GameObject gameObject = new GameObject(typeof(T).ToString());
			gameObject.transform.parent = transform;
			gameObject.transform.localPosition = Vector3.zero;
			gameObject.transform.localRotation = Quaternion.identity;
			gameObject.transform.localScale = Vector3.one;
			return gameObject.AddComponent<T>();
		}
		else
			return null;
	}
	
	#endregion
	
	#region add frame action
	[MenuItem ("Character/Add Frame Action/0 Create Object")]  
	static void CreateObjectOnFrame()
	{
		CreateNewFrameAction<CreateObject>();
	}
	
	[MenuItem ("Character/Add Frame Action/1 Play Sound")]  
	static void PlaySoundOnFrame()
	{
		CreateNewFrameAction<PlaySound>();
	}
	
	[MenuItem ("Character/Add Frame Action/2 AddDefenseShell")]  
	static void AddDefenseShellOnFrame()
	{
		CreateNewFrameAction<AddDefenseShell>();
	}

    [MenuItem ("Character/Add Frame Action/3 DieDown")]  
    static void DieDown()
    {
        CreateNewFrameAction<DieDown>();
    }

    [MenuItem ("Character/Add Frame Action/4 ActivateFlashEffect")]  
    static void ActivateFlashEffect()
    {
        CreateNewFrameAction<ActivateFlashEffect>();
    }

    [MenuItem ("Character/Add Frame Action/5 ChangePhysicsConstraintsEffect")]  
    static void ChangePhysicsConstraintsEffect()
    {
        CreateNewFrameAction<ChangePhysicsContraints>();
    }
	
    [MenuItem ("Character/Add Frame Action/6 CounterTriggerEffect")]  
    static void CounterTriggerEffect()
	{
        CreateNewFrameAction<CounterTrigger>();
	}

    [MenuItem ("Character/Add Frame Action/7 AddCameraEffect")]  
    static void AddCameraEffect()
    {
        CreateNewFrameAction<AddCameraEffect>();
    }
	
	[MenuItem ("Character/Add Frame Action/8 AddTimeScaleEffect")]  
	static void AddTimeScaleEffectOnFrame()
	{
		CreateNewFrameAction<AddTimeScaleEffect>();
	}
	
	[MenuItem ("Character/Add Frame Action/9 Set Target Rotation On Direction")]  
	static void SetTargetRotationOnDirection()
	{
		CreateNewFrameAction<SetTargetRotationOnDirection>();
	}
	
	[MenuItem ("Character/Add Frame Action/10 Turn To Target Rotation On Update")]  
	static void TurnToTargetRotationOnUpdate()
	{
		CreateNewFrameAction<TurnToTargetRotationOnUpdate>();
	}
	
	[MenuItem ("Character/Add Frame Action/11 Move On Direction")]  
	static void MoveOnDirection()
	{
		CreateNewFrameAction<MoveOnDirection>();
	}
	
	[MenuItem ("Character/Add Frame Action/12 Move By Speed On Update")]  
	static void MoveBySpeedOnUpdate()
	{
		CreateNewFrameAction<MoveBySpeedOnUpdate>();
	}
	
	[MenuItem ("Character/Add Frame Action/13 Move By Curve On Update")]  
	static void MoveByCurveOnUpdate()
	{
		CreateNewFrameAction<MoveByCurveOnUpdate>();
	}
	
	[MenuItem ("Character/Add Frame Action/14 Position By Curve On Update")]  
	static void PositionByCurveOnUpdate()
	{
		CreateNewFrameAction<PositionByCurveOnUpdate>();
	}
	
	[MenuItem ("Character/Add Frame Action/15 Position By Value On Update")]  
	static void PositionByValueOnUpdate()
	{
		CreateNewFrameAction<PositionByValueOnUpdate>();
	}
	
	[MenuItem ("Character/Add Frame Action/16 Position By Value Group On Update")]  
	static void PositionByValueGroupOnUpdate()
	{
		CreateNewFrameAction<PositionByValueGroupOnUpdate>();
	}
	
	[MenuItem ("Character/Add Frame Action/17 Injury")]  
	static void Injury()
	{
		Transform frame = FindParentForFrameAction();
		
		if(frame != null)
		{
			GameObject injuryObj = new GameObject("Injury");
			injuryObj.transform.parent = frame;
			ClearLocalTransform(injuryObj.transform);
			injuryObj.layer = frame.gameObject.layer;
			injuryObj.AddComponent<BoxCollider>();
			Injury injury = injuryObj.AddComponent<Injury>();
		}
	}
	
	[MenuItem ("Character/Add Frame Action/18 AnimateTiledTexture")]  
	static void AnimateTiledTexture()
	{
		CreateNewFrameAction<AnimateTiledTexture>();
	}	
	
	[MenuItem ("Character/Add Frame Action/Transition/19 Transition On Button")]  
	static void JumpToStateOnInput()
	{
		CreateNewFrameAction<TransitionOnButtonEvent>();
	}
	
	[MenuItem ("Character/Add Frame Action/Transition/20 Transition On Direction")]  
	static void JumpToStateOnDirection()
	{
		CreateNewFrameAction<TransitionOnDirectionEvent>();
	}
	
	//weapon trail
	[MenuItem ("Character/Add Frame Action/Transition/21 Emit Pocket RPG weapon Trail")]  
	static void JumpToStateOnEmitPocketRPGTrail()
	{
		CreateNewFrameAction<EmitRPGWeaponTrail>();
	}

    //Slash
    [MenuItem ("Character/Add Frame Action/Transition/22 SlashAction")]  
    static void OnSlashAction()
    {
        Transform frame = FindParentForFrameAction();
        
        if(frame != null)
        {
            GameObject slashObj = new GameObject("SlashAction");
            slashObj.transform.parent = frame;
            ClearLocalTransform(slashObj.transform);
            slashObj.layer = frame.gameObject.layer;
            slashObj.AddComponent<BoxCollider>();
            SlashAction slash = slashObj.AddComponent<SlashAction>();
        }
    }

	#endregion
	
	
	// Creates a prefab from the selected GameObjects.
	// if the prefab already exists it asks if you want to replace it    
	[MenuItem("Character/Save Character to prefab")]
	static void CreatePrefab() 
	{
		if(!System.IO.Directory.Exists("Assets/CharacterData/"))
		{
			System.IO.Directory.CreateDirectory("Assets/CharacterData/");
		}
		GameObject[] objs = Selection.gameObjects;
		if(objs.Length > 1)
		{
			EditorUtility.DisplayDialog("please choose only one gameobject!",
			                            "only one object", 
			                            "ok");
			return;
		}
		Character c = objs[0].GetComponent<Character>();
		if(c == null)
		{
			EditorUtility.DisplayDialog("please choose gameobject with character component!",
			                            "PanWithMouse Character Component",
			                            "ok");
			return;
		}
		foreach (GameObject go in objs) {
			string localPath = "Assets/CharacterData/" + go.name + ".prefab";
			
			if (AssetDatabase.LoadAssetAtPath(localPath, typeof(GameObject)))
			{
				if (EditorUtility.DisplayDialog("Are you sure?", 
				                                "The prefab already exists. Do you want to overwrite it?", 
				                                "Yes", 
				                                "No"))
				{
					CreateNew(go, localPath);
				}
			}
			else
			{
				CreateNew(go, localPath);
			}
		}
	}
	
	[MenuItem("Character/Save Character to prefab", true)]
	static bool ValidateCreatePrefab() 
	{
		return Selection.activeGameObject != null;
	}
	
	static void CreateNew(GameObject obj, string localPath)
	{
		Object prefab = PrefabUtility.CreateEmptyPrefab(localPath);
		PrefabUtility.ReplacePrefab(obj, prefab, ReplacePrefabOptions.ConnectToPrefab);
		PrefabUtility.DisconnectPrefabInstance(obj);
		EditorUtility.DisplayDialog("Successfully saved!",
		                            "saved Character data",
		                            "ok");
		
	}
	
	// Try to set the selected GameObject to a prefab state    
	[MenuItem("Character/Load Character to prefab %r")]
	static void Reset() 
	{
		GameObject[] objs = Selection.gameObjects;
		if(objs.Length > 1)
		{
			EditorUtility.DisplayDialog("please choose only one gameobject!",
			                            "only one object", 
			                            "ok");
			return;
		}
		Character c = objs[0].GetComponent<Character>();
		if(c == null)
		{
			EditorUtility.DisplayDialog("please choose gameobject with character component!",
			                            "PanWithMouse Character Component",
			                            "ok");
			return;
		}
		
		string localPath = "Assets/CharacterData/" + objs[0].name + ".prefab";
		
		Object prefab = AssetDatabase.LoadAssetAtPath(localPath, typeof(GameObject));
		
		GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
		Character cloned_character = go.GetComponent<Character>();
		PrefabUtility.DisconnectPrefabInstance(go);
		GameObject.DestroyImmediate(c.gameObject);
		
		
		/*
        if(PrefabUtility.RevertPrefabInstance(Selection.activeGameObject))
        {
            Debug.Log("RevertPrefabInstance to prefab state successfully!");
        }

       
        if(PrefabUtility.ResetToPrefabState(Selection.activeGameObject))
        {
            Debug.Log("Reseted to prefab state successfully!");
        }
        else
        {
            Debug.LogError("Couldnt reset to a prefab state " + Selection.activeGameObject.name);
        }
        */
		
	}
	[MenuItem("Character/Load Character to prefab %r", true)]
	static bool CheckReset()
	{
		return Selection.activeGameObject != null;
	}
	
}

